package com.ticorp.framework.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Date Utility Class This is used to convert Strings to Dates and Timestamps
 * 
 * <p>
 * <a href="DateUtil.java.html"><i>View Source</i></a>
 * </p>
 * 
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a> Modified by
 *         <a href="mailto:dan@getrolling.com">Dan Kibler </a> to correct time
 *         pattern. Minutes should be mm not MM (MM is month).
 * @version $Revision: 1.1.2.1 $ $Date: 2006/11/08 21:23:22 $
 */
public class DateUtil {
    private static Log log = LogFactory.getLog(DateUtil.class);

    private static String datePattern = "dd/MM/yyyy";
    private static String timePattern = "HH:mm:ss";

    /**
     * Return default datePattern
     * 
     * @return a string representing the date pattern on the UI
     */
    public static String getDatePattern() {
	return datePattern;
    }

    /**
     * This method attempts to convert an Oracle-formatted date in the form
     * dd-MMM-yyyy to mm/dd/yyyy.
     * 
     * @param aDate
     *            date from database as a string
     * @return formatted string for the ui
     */
    public static final String getDate(Date aDate) {
	SimpleDateFormat df = null;
	String returnValue = "";

	if (aDate != null) {
	    df = new SimpleDateFormat(datePattern);
	    returnValue = df.format(aDate);
	}

	return (returnValue);
    }

    /**
     * This method attempts to convert an Oracle-formatted date in Time format
     * HH:mm
     * 
     * @param aDate
     *            date from database as a string
     * @return formatted string for the ui
     */
    public static final String getTime(Date aDate) {
	SimpleDateFormat df = null;
	String returnValue = "";

	if (aDate != null) {
	    df = new SimpleDateFormat(timePattern);
	    returnValue = df.format(aDate);
	}

	return (returnValue);
    }

    /**
     * This method generates a string representation of a date/time in the
     * format you specify on input
     * 
     * @param aMask
     *            the date pattern the string is in
     * @param strDate
     *            a string representation of a date
     * @return a converted Date object
     * @see java.text.SimpleDateFormat
     * @throws ParseException
     */
    public static final Date convertStringToDate(String aMask, String strDate) throws ParseException {
	SimpleDateFormat df = null;
	Date date = null;
	df = new SimpleDateFormat(aMask);

	if (log.isDebugEnabled()) {
	    log.debug("converting '" + strDate + "' to date with mask '" + aMask + "'");
	}

	try {
	    date = df.parse(strDate);
	} catch (ParseException pe) {
	    // log.error("ParseException: " + pe);
	    throw new ParseException(pe.getMessage(), pe.getErrorOffset());
	}

	return (date);
    }

    /**
     * This method returns the current date time in the format: MM/dd/yyyy HH:MM
     * a
     * 
     * @param theTime
     *            the current time
     * @return the current date/time
     */
    public static String getTimeNow(Date theTime) {
	return getDateTime(timePattern, theTime);
    }

    public static String getDateNow() {
	return convertDateToString(new Date());
    }

    /**
     * This method returns the current date in the format: dd/MM/yyyy
     * 
     * @return the current date
     * @throws ParseException
     */
    public static Calendar getToday() throws ParseException {
	Date today = new Date();
	SimpleDateFormat df = new SimpleDateFormat(datePattern);

	// This seems like quite a hack (date -> string -> date),
	// but it works ;-)
	String todayAsString = df.format(today);
	Calendar cal = new GregorianCalendar();
	cal.setTime(convertStringToDate(todayAsString));

	return cal;
    }

    /**
     * This method generates a string representation of a date's date/time in
     * the format you specify on input
     * 
     * @param aMask
     *            the date pattern the string is in
     * @param aDate
     *            a date object
     * @return a formatted string representation of the date
     * 
     * @see java.text.SimpleDateFormat
     */
    public static final String getDateTime(String aMask, Date aDate) {
	SimpleDateFormat df = null;
	String returnValue = "";

	if (aDate == null) {
	    log.error("aDate is null!");
	} else {
	    df = new SimpleDateFormat(aMask);
	    returnValue = df.format(aDate);
	}

	return (returnValue);
    }

    /**
     * This method generates a string representation of a date based on the
     * System Property 'dateFormat' in the format you specify on input
     * 
     * @param aDate
     *            A date to convert
     * @return a string representation of the date
     */
    public static final String convertDateToString(Date aDate) {
	return getDateTime(datePattern, aDate);
    }

    /**
     * This method converts a String to a date using the datePattern
     * 
     * @param strDate
     *            the date to convert (in format MM/dd/yyyy)
     * @return a date object
     * 
     * @throws ParseException
     */
    public static Date convertStringToDate(String strDate) throws ParseException {
	Date aDate = null;

	try {
	    if (log.isDebugEnabled()) {
		log.debug("converting date with pattern: " + datePattern);
	    }

	    aDate = convertStringToDate(datePattern, strDate);
	} catch (ParseException pe) {
	    log.error("Could not convert '" + strDate + "' to a date, throwing exception", pe);
	    throw new ParseException(pe.getMessage(), pe.getErrorOffset());

	}

	return aDate;
    }

    /**
     * Convierte del formato <i>yyyyMMdd</i> al formato <i>dd/MM/yyyy</i>. <br />
     * Ej: 20061231 a 31/12/2006
     * 
     * @param fechaProceso
     *            String con el formato <i>yyyyMMdd</i>
     * @return String con el formato <i>dd/MM/yyyy</i>
     */
    public static String convierteFormatoFecha(String fecha) {
	String resultado = "";
	resultado = fecha.substring(6) + fecha.substring(3, 5) + fecha.substring(0, 2);
	return resultado;
    }

    public static String convierteFecha(String fecha) {
	String resultado = "";
	resultado = fecha.substring(6, 8) + "/" + fecha.substring(4, 6) + "/" + fecha.substring(0, 4);
	return resultado;
    }

    public static final Date convertStringToTime(String strTime) throws ParseException {
	SimpleDateFormat df = null;
	Date date = null;
	df = new SimpleDateFormat(timePattern);

	if (log.isDebugEnabled()) {
	    log.debug("converting '" + strTime + "' to date with mask '" + timePattern + "'");
	}

	try {
	    date = df.parse(strTime);
	} catch (ParseException pe) {
	    // log.error("ParseException: " + pe);
	    throw new ParseException(pe.getMessage(), pe.getErrorOffset());
	}

	return (date);
    }

    public static String getTodayDesc() {
	SimpleDateFormat sdf = null;
	Date date = new Date();

	sdf = new SimpleDateFormat("EEEEEEEEE");
	String dia = StringUtils.capitalize(sdf.format(date));

	sdf = new SimpleDateFormat("d");
	String fecha = sdf.format(date);

	sdf = new SimpleDateFormat("MMMMMMMMM");
	String mes = StringUtils.capitalize(sdf.format(date));

	sdf = new SimpleDateFormat("yyyy");
	String anio = sdf.format(date);

	return dia + ", " + fecha + " de " + mes + " de " + anio;
    }

    /**
     * Metodo que permite agregar a la fecha a modificar (fechaModificar) una
     * cantidad de determinada unidad (cantidadAgregar): dias, meses o anhos. Si
     * se quiere reducir de la fecha un valor, se usa el parametro
     * cantidadAgregar con un valor negativo. Por ejemplo: addToDate(new Date(),
     * 5, Calendar.DATE) -- agrega 5 dias a la fecha actual addToDate(new
     * Date(), -2, Calendar.MONTH) -- Resta 2 meses de la fecha actual
     * addToDate(new Date(), 3, Calendar.YEAR) -- Agrega 3 anhos a la fecha
     * actual
     * 
     * @param fechaModificar
     *            fecha que va a ser modificada
     * @param cantidadAgregar
     *            unidades a agregar o sustraer a la fecha actual
     * @param tipoDateConvertir
     *            si se va a sumar (o restar) Dias (Calendar.DATE), Meses
     *            (Calendar.MONTH) o anhos (Calendar.YEAR)
     * 
     * @return
     */
    private static Date addToDate(Date fechaModificar, int cantidadAgregar, int tipoDateConvertir) {
	Calendar cal = Calendar.getInstance();
	cal.setTime(fechaModificar);
	cal.add(tipoDateConvertir, cantidadAgregar);
	return cal.getTime();
    }

    /**
     * Agrega (sustrae) dias a la fecha actual
     * 
     * @param fechaModificar
     * @param cantidadDias
     * @return
     */
    public static Date addDayToDate(Date fechaModificar, int cantidadDias) {
	return addToDate(fechaModificar, cantidadDias, Calendar.DATE);
    }

    /**
     * Agrega (sustrae) meses a la fecha actual
     * 
     * @param fechaModificar
     * @param cantidadMeses
     * @return
     */
    public static Date addMonthToDate(Date fechaModificar, int cantidadMeses) {
	return addToDate(fechaModificar, cantidadMeses, Calendar.MONTH);
    }

    /**
     * Agrega (sustrae) anhos a la fecha actual
     * 
     * @param fechaModificar
     * @param cantidadAnhos
     * @return
     */
    public static Date addYearToDate(Date fechaModificar, int cantidadAnhos) {
	return addToDate(fechaModificar, cantidadAnhos, Calendar.YEAR);
    }

}
